﻿// MIT License (MIT)
// 
// Copyright (c) 2014 K Ercan Turkarslan
// 
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
// 
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
// 
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
// 

#define USE_USERDATA    // Uses user_data to retrieve configuration and polling
#define USE_SDATA       // Uses sdata to retrieve configuration and polling

using System;
using System.Threading;
using Mios;
using Mios.Generated.DeviceFiles;
using Mios.MiosConnection;

namespace TestApp
{
    public static class Program
    {
        static void Main()
        {
            // ----------------------------------------------------------------
            // Mios library provides GetCapability static method which returns an enum value { MINIMAL, SDATA, USERDATA, BOTH }
            // If you are loading Mios Library, you can use this static method to find out capabilities of the Mios library.
            //
            // Normally, you will NOT need following static method call. 
            // var capability = LibraryCapabilities.GetCapability();

            ////----------------------------------------------------------------
            //// How to find UI5 MiosControllers (Local and Remote)
            //// 
            //// Set A : All UI5 controllers that are in the local network. May belong to different users.
            //// Set B : All UI5 controllers that belongs to specified user. These may be in the local network or at remote location.
            ////----------------------------------------------------------------

            //var ui5Controllers = new Ui5Controllers();                          // Set A
            //// or
            //// var ui5Controllers = new Ui5Controllers(Username, Password, false); // Set A + Set B
            //// or
            //// var ui5Controllers = new Ui5Controllers(Username, Password, true);  // Set B

            //foreach (var controller in ui5Controllers.Controllers)
            //{
            //    Console.WriteLine(String.Format("Engine Serial            : {0}", controller.EngineSerial));
            //    Console.WriteLine(String.Format("Username                 : {0}", controller.Username));
            //    Console.WriteLine(String.Format("Password                 : {0}", controller.Password));

            //    if (controller.CanConnectLocally())
            //    {
            //        Console.WriteLine(String.Format("IP Address               : {0}", controller.LocalIpAddress));
            //    }

            //    Console.WriteLine(String.Format("Primary Forward Server   : {0}", controller.PrimaryForwardServer));
            //    Console.WriteLine(String.Format("Secondary Forward Server : {0}", controller.SecondaryForwardServer));
            //}


            ////----------------------------------------------------------------
            //// How to find UI7 MiosControllers (Local and Remote)
            ////----------------------------------------------------------------
            //var AuthenticationServer = "vera-us-oem-autha.mios.com";
            //var PasswordSeed = "oZ7QE6LcLJp6fiWzdqZc"; // Change this seed for better security
            //var PkOem = "1";

            //var ui7Controllers = new Ui7Controllers(AuthenticationServer, Username, Password, PasswordSeed, PkOem);

            //foreach (var controller in ui7Controllers.Controllers)
            //{
            //    Console.WriteLine(String.Format("Engine Serial            : {0}", controller.EngineSerial));
            //    Console.WriteLine(String.Format("Username                 : {0}", controller.Username));
            //    Console.WriteLine(String.Format("Password                 : {0}", controller.Password));
            //
            //    if (controller.CanConnectLocally())
            //    {
            //        Console.WriteLine(String.Format("IP Address               : {0}", controller.LocalIpAddress));
            //        Console.WriteLine(String.Format("MAC Address              : {0}", controller.ControllerDetail.MacAddress));
            //    }
            //
            //    Console.WriteLine(String.Format("Device Server            : {0}", controller.DeviceServer));
            //    Console.WriteLine(String.Format("Relay Server             : {0}", controller.ControllerDetail.RelayServer));
            //    Console.WriteLine(String.Format("External IP Address      : {0}", controller.ControllerDetail.ExternalIp));
            //}

            // Following code assumes you don't know UI of controller. It looks for Ui5Controllers with specified engine serial.
            // If not found, looks for Ui7Controllers.
            var ui5Controllers = new Ui5Controllers("username", "password", true);
            var myController = (MiosController) ui5Controllers.GetController("12345678");

            if (myController == null)
            {
                // We could not find any Ui5 controllers with given username password
                // We will look for Ui7 controllers
                var ui7Controllers = new Ui7Controllers("vera-us-oem-autha.mios.com", "username", "password", "passwordseed", "1");            

                myController = ui7Controllers.GetController("12345678");
            }

            if (myController == null)
            {
                // We did not find any Ui5 or Ui7 controllers. We can't continue.
                throw new InvalidOperationException("No controller found with provided credentials!");
            }

            // If you don't call EstablisthRemoteConnectio or EstablishLocalConnection,
            // MiosEngine constructor will implicitly connect locally or remotely.
            // 
            // If you want to connect remotely even if you are in the local network, 
            // you have to call EstablishRemoteConnection explicitly.
            myController.EstablishRemoteConnection();

            var miosEngine = new MiosEngine(myController);

#if USE_USERDATA
            // Use this code path if you would like to populate Section, Room, Scene and Device information via a single USER_DATA luup request
            // This code path takes less time to populate (1/10th of SDATA). However it downloads 20 times more data than SDATA code path.

            var miosData = new UserData(miosEngine);

            // If configuration is populated you can use device name to create an instance
            var officeLight = (BinaryLight1) miosEngine.GetDeviceByName("Office Light");

#elif USE_SDATA
            // Use this code path if you would like to populate Section, Room, Scene and Device information using SDATA and multiple finddevice Luup requests
            // This code path takes longer to populate.

            var miosData = new SummaryData(miosEngine);

            // If configuration is populated you can use device name to create an instance
            var officeLight = (BinaryLight1) miosEngine.GetDeviceByName("Office Light");

#else
            // You don't need to populate configuration data to create a device instance.
            // If you know the device id and device type, you can directly create the device.
            // If you are targetting .NET Micro Framework (e.g. Netduino), you may consider this.
            var officeLight = new BinaryLight1(miosEngine, 20);

#endif


#if USE_SDATA || USE_USERDATA
            // Following method retrieves latest values from your home automation controller.
            miosData.Poll();
#endif

            // Executes SetTarget action to turn off the device.
            officeLight.SSwitchPower1.SetTarget(false);

            Thread.Sleep(2000);

#if USE_SDATA || USE_USERDATA
            // If you set a breakpoint after this comment and turn on the light manually
            // changes will be picked up after miosData.Poll() method call.
            // One important note. When you call SetTarget at Mios Controller you are changing
            // Status variable not the Target variable.
            miosData.Poll();
#endif

            // Executes SetTarget action to turn on the device.
            officeLight.SSwitchPower1.SetTarget(true);
            Thread.Sleep(2000);
            officeLight.SHaDevice1.ToggleState();
            Thread.Sleep(2000);
            officeLight.SHaDevice1.ToggleState();

#if USE_SDATA || USE_USERDATA
            miosData.Poll();
#endif
        }
    }
}
